package com.company.cloud.pay.modules.pay.service.impl;

import cn.hutool.core.util.IdUtil;
import com.company.cloud.common.constant.BaseConstant;
import com.company.cloud.common.constant.BaseConstant.YNEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.pay.constant.PayNotityStateEnum;
import com.company.cloud.pay.modules.api.constant.PayStateEnum;
import com.company.cloud.pay.modules.api.request.PayBaseRequest;
import com.company.cloud.pay.modules.api.request.PayOrderCloseRequest;
import com.company.cloud.pay.modules.api.request.PayOrderQueryRequest;
import com.company.cloud.pay.modules.api.request.PayOrderRequest;
import com.company.cloud.pay.modules.api.response.PayOrderCloseResponse;
import com.company.cloud.pay.modules.api.response.PayOrderQueryResponse;
import com.company.cloud.pay.modules.api.response.PayOrderResponse;
import com.company.cloud.pay.modules.base.entity.PayPaymentOrderInfo;
import com.company.cloud.pay.modules.base.entity.PayThirdCallLog;
import com.company.cloud.pay.modules.base.service.PayPaymentOrderInfoService;
import com.company.cloud.pay.modules.base.service.PayThirdCallLogService;
import com.company.cloud.pay.modules.bus.producer.PayProducer;
import com.company.cloud.pay.modules.cache.model.PayChannelConfigModel;
import com.company.cloud.pay.modules.cache.model.PayServiceConfigModel;
import com.company.cloud.pay.modules.cache.service.PayCacheService;
import com.company.cloud.pay.modules.pay.service.UnifiedPayService;
import com.company.cloud.pay.modules.third.factory.CloudPayApiFactory;
import com.company.cloud.pay.modules.third.factory.CloudPayApiService;
import com.company.cloud.pay.modules.third.models.ThirdPayResp;
import com.company.cloud.pay.modules.third.models.ThirdQueryOrderResp;
import com.company.cloud.pay.modules.third.models.ThirdUnifiedOrderResp;
import com.company.common.server.config.cloud.ProjectConfig;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Objects;

@Log4j2
@Service
public class UnifiedPayServiceImpl implements UnifiedPayService {

    @Autowired
    private PayCacheService payCacheService;

    @Autowired
    private PayThirdCallLogService payThirdCallLogService;

    @Autowired
    private PayPaymentOrderInfoService payPaymentOrderInfoService;

    @Autowired
    private PayProducer payProducerUtils;

    @Autowired
    private ProjectConfig projectConfig;

    /**
     * 统一下单
     */
    @SuppressWarnings("unused")
    @Transactional
    @Override
    public PayOrderResponse payOrderInfo(PayOrderRequest request) {
        log.debug("+++++统一下单 >>> ");
        request.setAttach(IdUtil.getSnowflake(8, 8).nextIdStr());
        // 校验支付服务号
        PayServiceConfigModel payServiceAcct = this.validatePayService(request);
        // 获取和校验支付通道
        PayChannelConfigModel payConfig = this.validate2getPayChannel(request);
        // 调用第三方支付
        CloudPayApiService cloudPayApiService = CloudPayApiFactory.getCloudPayApi(request.getPtt().getPayChannel());
        assert cloudPayApiService != null;
        ThirdUnifiedOrderResp respModel = cloudPayApiService.unifiedOrder(payConfig.getPayChannelParam(), request);
        // 处理支付流水
        PayPaymentOrderInfo paymentOrder = this.getPayPaymentOrder(request.getAttach(), request);
        payPaymentOrderInfoService.save(paymentOrder);
        // 处理支付调用日志
        PayThirdCallLog payLog = this.getPayThirdCallLog(request, respModel, "payOrderInfo", "统一下单");
        payThirdCallLogService.save(payLog);

        return new PayOrderResponse(respModel.getRetCode(), respModel.getRetMsg(), respModel.getBiz());
    }

    @SuppressWarnings("unused")
    @Transactional
    @Override
    public PayOrderCloseResponse payOrderClose(PayOrderCloseRequest request) {
        // 校验支付服务号
        PayServiceConfigModel payServiceAcct = this.validatePayService(request);
        // 获取和校验支付通道
        PayChannelConfigModel payConfig = this.validate2getPayChannel(request);
        // 调用第三方支付
        CloudPayApiService cloudPayApiService = CloudPayApiFactory.getCloudPayApi(request.getPtt().getPayChannel());
        ThirdPayResp respModel = cloudPayApiService.closeOrder(payConfig.getPayChannelParam(), request);
        // 处理支付调用日志
        PayThirdCallLog payLog = this.getPayThirdCallLog(request, respModel, "payOrderClose", "关闭订单");
        payThirdCallLogService.save(payLog);

        return new PayOrderCloseResponse(respModel.getRetCode(), respModel.getRetMsg());
    }

    @SuppressWarnings("unused")
    @Transactional
    @Override
    public PayOrderQueryResponse payOrderQuery(PayOrderQueryRequest request) {
        // 校验支付服务号
        PayServiceConfigModel payServiceAcct = this.validatePayService(request);
        // 获取和校验支付通道
        PayChannelConfigModel payConfig = this.validate2getPayChannel(request);
        // 调用第三方支付
        CloudPayApiService cloudPayApiService = CloudPayApiFactory.getCloudPayApi(request.getPtt().getPayChannel());
        ThirdQueryOrderResp respModel = cloudPayApiService.queryOrder(payConfig.getPayChannelParam(), request);
        // 处理支付调用日志
        PayThirdCallLog payLog = this.getPayThirdCallLog(request, respModel, "payOrderQuery", "查询订单");
        payThirdCallLogService.save(payLog);

        PayOrderQueryResponse result = new PayOrderQueryResponse(respModel.getRetCode(), respModel.getRetMsg(),
                respModel.getOutTradeNo(), respModel.getState().getCode(), respModel.getTradeState());

        payProducerUtils.payOrderQuery(payConfig.getServiceCode(), payConfig.getCompanyNo(), respModel);
        return result;
    }

    /**
     * 支付流水信息
     */
    private PayPaymentOrderInfo getPayPaymentOrder(String sn, PayOrderRequest request) {
        PayPaymentOrderInfo entity = new PayPaymentOrderInfo();
        entity.setSn(sn);
        entity.setCompanyNo(request.getCompanyNo());
        entity.setServiceCode(request.getServiceCode());
        entity.setPayChannelNo(request.getPtt().getPayChannel());
        entity.setPayWay(request.getPtt().getTradeType());
        entity.setOutSn(request.getOutTradeNo());
        entity.setFund(request.getTotalFee());
        entity.setState(PayStateEnum.Pay_Not.getCode());
        entity.setApplyDate(LocalDateTime.now());
        entity.setApplyUser(String.valueOf(request.getOpUserId()));
        entity.setApplyIp(request.getOpIp());
        entity.setNotityState(PayNotityStateEnum.PN_Not.getCode());
        entity.setNotityNum(0);
        return entity;
    }

    /**
     * 日志
     */
    private PayThirdCallLog getPayThirdCallLog(PayBaseRequest reqBase, ThirdPayResp resp, String thirdMethodCode,
                                               String thirdMethodName) {
        PayThirdCallLog entity = new PayThirdCallLog();
        entity.setServiceCode(reqBase.getServiceCode());
        entity.setCompanyNo(reqBase.getCompanyNo());
        entity.setPayChannelNo(reqBase.getPtt().getPayChannel());
        entity.setPayWay(reqBase.getPtt().getTradeType());
        entity.setThirdMethodCode(thirdMethodCode);
        entity.setThirdMethodName(thirdMethodName);
        entity.setReqParam(resp.getReq());
        entity.setRespParam(resp.getResp());
        entity.setCdt(LocalDateTime.now());
        entity.setCip(reqBase.getOpIp());
        entity.setCman(reqBase.getOpUserId());
        return entity;
    }


    /**
     * 验证支付服务号
     */
    private PayServiceConfigModel validatePayService(PayBaseRequest request) {
        PayServiceConfigModel payServiceConfig = payCacheService.getPayServiceConfigByCache(request.getServiceCode());
        if (YNEnum.NO.getCode().equals(payServiceConfig.getState())) {
            throw new BusinessException("暂停支付服务");
        }
        // todo
        return payServiceConfig;
    }

    /**
     * 验证支付通道配置
     */
    private PayChannelConfigModel validate2getPayChannel(PayBaseRequest request) {
        PayChannelConfigModel payChannelConfig = null;
        if (projectConfig.isCompanyPay()) {
            payChannelConfig = payCacheService.getPayChannelConfigByCache(request.getServiceCode(),
                    request.getCompanyNo(), request.getPtt().getPayChannel(), request.getPtt().getTradeType());
        }
        if (projectConfig.isPlatformPay()) {
            payChannelConfig = payCacheService.getPayChannelConfigByCache(request.getServiceCode(),
                    BaseConstant.Platform_Company, request.getPtt().getPayChannel(), request.getPtt().getTradeType());
        }
        if (projectConfig.isCompany2PlatformPay()) {
            payChannelConfig = payCacheService.getPayChannelConfigByCache(request.getServiceCode(),
                    request.getCompanyNo(), request.getPtt().getPayChannel(), request.getPtt().getTradeType());
            log.info("projectConfigLogin==============="+request.getServiceCode()+"=============================");
            log.info("projectConfigLogin==============="+ request.getCompanyNo()+"=============================");
            log.info("projectConfigLogin==============="+request.getPtt().getPayChannel()+"=============================");
            log.info("projectConfigLogin==============="+request.getPtt().getTradeType()+"=============================");
            if (payChannelConfig == null) {
                payChannelConfig = payCacheService.getPayChannelConfigByCache(request.getServiceCode(),
                        BaseConstant.Platform_Company, request.getPtt().getPayChannel(), request.getPtt().getTradeType());
            }
        }
        if (payChannelConfig == null) {
            throw new BusinessException("未配置支付通道");
        }
        if (YNEnum.NO.getCode().equals(payChannelConfig.getState())) {
            throw new BusinessException("暂停支付通道");
        }
        payChannelConfig.getPayChannelParam().setConfigId(payChannelConfig.getId());
        return payChannelConfig;
    }

}
